/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package systole.domain.report.builder;

import com.itextpdf.text.BadElementException;
import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.DefaultFontMapper;
import com.itextpdf.text.pdf.FontMapper;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import systole.domain.analysis.Analysis;
import systole.domain.analysis.results.AnalysisResult;
import systole.domain.analysis.results.averages.AverageByDecade;
import systole.domain.persons.Medic;
import systole.domain.persons.Patient;
import systole.domain.report.Report;
import systole.exceptions.ExceptionDAO;
import systole.persistence.FacadeDB;
import systole.propertiesController.ReportSettingsProperties;
import systole.utils.ImageUtils;
import systole.utils.Units;
import systole.view.messages.EntityDescriptions;
import systole.view.messages.ReportTexts;

/**
 *
 * @author jmj
 */
public class ClasicReportBuilder extends ReportBuilder {

    private FontMapper fontMapper;

    /**
     * 
     */
    public ClasicReportBuilder() {
        super();
        this.fontMapper = new DefaultFontMapper();
    }

    @Override
    protected void buildHeader() throws DocumentException, IOException, MalformedURLException {

        float[] widiths = {0.5f, 2f, 0.5f};
        PdfPTable table = new PdfPTable(widiths);
        table.setWidthPercentage(90);
        PdfPCell imageL = new PdfPCell();
        PdfPCell imageR = new PdfPCell();

        if (this.reportSettingsProperties.loadUseLeftImage()) {
            BufferedImage leftImg = ImageUtils.loadImage(ImageUtils.IMAGES_FOLDER + System.getProperty("file.separator") + ReportSettingsProperties.FILE_NAME_LEFT_IMAGE);
            if (leftImg != null) {
                Image leftPdfImage = Image.getInstance(leftImg, null);
                leftPdfImage = this.scaleImage(leftPdfImage, this.reportSettingsProperties.loadLeftImageSize());
                leftPdfImage.setAlignment(Image.ALIGN_MIDDLE);
                imageL.setImage(leftPdfImage);
                imageL.setHorizontalAlignment(Element.ALIGN_MIDDLE);
                imageL.setVerticalAlignment(Element.ALIGN_CENTER);
            }
        }

        if (this.reportSettingsProperties.loadUseRightImage()) {
            BufferedImage rightImg = ImageUtils.loadImage(ImageUtils.IMAGES_FOLDER + System.getProperty("file.separator") + ReportSettingsProperties.FILE_NAME_RIGHT_IMAGE);
            if (rightImg != null) {
                Image rightImage = Image.getInstance(rightImg, null);
                rightImage.setAlignment(Image.ALIGN_MIDDLE);
                imageR.setImage(rightImage);
                imageR.setHorizontalAlignment(Element.ALIGN_MIDDLE);
                imageR.setVerticalAlignment(Element.ALIGN_CENTER);
            }
        }

        table.addCell(imageL);
        Chunk par = new Chunk(this.reportSettingsProperties.loadTitle());
        par.setFont(new Font(this.fontMapper.awtToPdf(this.reportSettingsProperties.loadTitleFont())));
        Paragraph enc = new Paragraph(par);
        enc.setAlignment(Element.ALIGN_CENTER);
        PdfPCell cell = new PdfPCell();
        cell.addElement(enc);
        cell.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        table.addCell(cell);
        table.addCell(imageR);
        this.document.add(table);
        this.writeEmptyLine();
    }

    @Override
    protected void buildPatientInfo(Analysis analysis) throws DocumentException {

        Patient patient = analysis.getPatient();
        Chunk pat = new Chunk(EntityDescriptions.PATIENT + ": " + patient.getFullName());
        pat.setFont(new Font(Font.FontFamily.TIMES_ROMAN, 14, Font.BOLD));
        this.document.add(pat);
        this.document.add(Chunk.NEWLINE);
        this.document.add(Chunk.NEWLINE);

        Medic medic = analysis.getMedic();
        if (medic != null) {
            Chunk med = new Chunk(ReportTexts.request_by + medic.getFullName());
            med.setFont(new Font(Font.FontFamily.TIMES_ROMAN, 12, Font.BOLD));
            this.document.add(med);
            this.writeEmptyLine();
        }

        int amount = this.getAmountOfData();

        if (amount > 0) {
            PdfPTable patientTable = new PdfPTable(amount);
            patientTable.setWidthPercentage(90);

            Font title = new Font(this.fontMapper.awtToPdf(this.reportSettingsProperties.loadDataFont()));
            Font value = new Font(this.fontMapper.awtToPdf(this.reportSettingsProperties.loadDataValueFont()));

            // PUT HEADERS

            if (this.reportSettingsProperties.loadUseAge()) {
                Chunk a = new Chunk("Edad");
                a.setFont(title);
                PdfPCell ages = new PdfPCell(new Paragraph(a));
                ages.setHorizontalAlignment(Element.ALIGN_CENTER);
                ages.setVerticalAlignment(Element.ALIGN_MIDDLE);
                patientTable.addCell(ages);
            }

            if (this.reportSettingsProperties.loadUseWeight()) {
                Chunk p = new Chunk("Peso" + System.getProperty("line.separator") + Units.kilograms);
                p.setFont(title);
                PdfPCell weight = new PdfPCell(new Paragraph(p));
                weight.setHorizontalAlignment(Element.ALIGN_CENTER);
                weight.setVerticalAlignment(Element.ALIGN_MIDDLE);
                patientTable.addCell(weight);
            }

            if (this.reportSettingsProperties.loadUseHeight()) {
                Chunk h = new Chunk("Altura" + System.getProperty("line.separator") + Units.Centimetres);
                h.setFont(title);
                PdfPCell height = new PdfPCell(new Paragraph(h));
                height.setHorizontalAlignment(Element.ALIGN_CENTER);
                height.setVerticalAlignment(Element.ALIGN_MIDDLE);
                patientTable.addCell(height);
            }

            if (this.reportSettingsProperties.loadUsePS()) {
                Chunk pss = new Chunk("PS" + System.getProperty("line.separator") + Units.pressure);
                pss.setFont(title);
                PdfPCell ps = new PdfPCell(new Paragraph(pss));
                ps.setHorizontalAlignment(Element.ALIGN_CENTER);
                ps.setVerticalAlignment(Element.ALIGN_MIDDLE);
                patientTable.addCell(ps);
            }

            if (this.reportSettingsProperties.loadUsePD()) {
                Chunk pdd = new Chunk("PD" + System.getProperty("line.separator") + Units.pressure);
                pdd.setFont(title);
                PdfPCell pd = new PdfPCell(new Paragraph(pdd));
                pd.setHorizontalAlignment(Element.ALIGN_CENTER);
                pd.setVerticalAlignment(Element.ALIGN_MIDDLE);
                patientTable.addCell(pd);
            }

            if (this.reportSettingsProperties.loadUseSmoke()) {
                Chunk sm = new Chunk("Fuma");
                sm.setFont(title);
                PdfPCell smooke = new PdfPCell(new Paragraph(sm));
                smooke.setHorizontalAlignment(Element.ALIGN_CENTER);
                smooke.setVerticalAlignment(Element.ALIGN_MIDDLE);
                patientTable.addCell(smooke);
            }

            // PUT DATA

            if (this.reportSettingsProperties.loadUseAge()) {
                Chunk years = new Chunk(patient.getAge().toString());
                years.setFont(value);
                PdfPCell agesValue = new PdfPCell(new Paragraph(years));
                agesValue.setHorizontalAlignment(Element.ALIGN_CENTER);
                agesValue.setVerticalAlignment(Element.ALIGN_MIDDLE);
                patientTable.addCell(agesValue);
            }

            if (this.reportSettingsProperties.loadUseWeight()) {
                Chunk weightP = new Chunk(analysis.getClinicalInformation().getWeightAsString(false));
                weightP.setFont(value);
                PdfPCell weightValue = new PdfPCell(new Paragraph(weightP));
                weightValue.setHorizontalAlignment(Element.ALIGN_CENTER);
                weightValue.setVerticalAlignment(Element.ALIGN_MIDDLE);
                patientTable.addCell(weightValue);
            }

            if (this.reportSettingsProperties.loadUseHeight()) {
                Chunk heightP = new Chunk(analysis.getClinicalInformation().getHeightAsString(false));
                heightP.setFont(value);
                PdfPCell heightValue = new PdfPCell(new Paragraph(heightP));
                heightValue.setHorizontalAlignment(Element.ALIGN_CENTER);
                heightValue.setVerticalAlignment(Element.ALIGN_MIDDLE);
                patientTable.addCell(heightValue);
            }

            if (this.reportSettingsProperties.loadUsePS()) {
                Chunk psCk = new Chunk(analysis.getClinicalInformation().getSystolicPressureAsString(false));
                psCk.setFont(value);
                PdfPCell psValue = new PdfPCell(new Paragraph(psCk));
                psValue.setHorizontalAlignment(Element.ALIGN_CENTER);
                psValue.setVerticalAlignment(Element.ALIGN_MIDDLE);
                patientTable.addCell(psValue);
            }

            if (this.reportSettingsProperties.loadUsePD()) {
                Chunk pdCk = new Chunk(analysis.getClinicalInformation().getDiastolicPressureAsString(false));
                pdCk.setFont(value);
                PdfPCell pdValue = new PdfPCell(new Paragraph(pdCk));
                pdValue.setHorizontalAlignment(Element.ALIGN_CENTER);
                pdValue.setVerticalAlignment(Element.ALIGN_MIDDLE);
                patientTable.addCell(pdValue);
            }

            if (this.reportSettingsProperties.loadUseSmoke()) {
                Chunk smk = new Chunk(patient.getClinicalHistoryProxy().getIsSmoker());
                smk.setFont(value);
                PdfPCell smookeValue = new PdfPCell(new Paragraph(smk));
                smookeValue.setHorizontalAlignment(Element.ALIGN_CENTER);
                smookeValue.setVerticalAlignment(Element.ALIGN_MIDDLE);
                patientTable.addCell(smookeValue);
            }
            this.document.add(patientTable);
        }

        this.writeEmptyLine();
    }

    @Override
    protected void buildParamsInfo(Analysis analysis, Report report, AnalysisResult analysisResult) throws DocumentException {

        Font indexFont = new Font(fontMapper.awtToPdf(this.reportSettingsProperties.loadIndexFont()));
        Font indexValueFont = new Font(fontMapper.awtToPdf(this.reportSettingsProperties.loadIndexValueFont()));

        int amount = this.getAmountOfIndex();

        if (amount > 0) {

            PdfPTable indicesTable = new PdfPTable(amount);
            indicesTable.setWidthPercentage(90);

            // PUT HEADER

            if (this.reportSettingsProperties.loadUseAOD()) {
                Chunk amp = new Chunk("Amplitud OD" + System.getProperty("line.separator") + Units.amplitude);
                amp.setFont(indexFont);
                PdfPCell amplitud = new PdfPCell(new Paragraph(amp));
                amplitud.setHorizontalAlignment(Element.ALIGN_CENTER);
                amplitud.setVerticalAlignment(Element.ALIGN_MIDDLE);
                indicesTable.addCell(amplitud);
            }

            if (this.reportSettingsProperties.loadUseIAR()) {
                Chunk aume = new Chunk("Aumentación" + System.getProperty("line.separator") + Units.amplitude);
                aume.setFont(indexFont);
                PdfPCell aumentacion = new PdfPCell(new Paragraph(aume));
                aumentacion.setHorizontalAlignment(Element.ALIGN_CENTER);
                aumentacion.setVerticalAlignment(Element.ALIGN_MIDDLE);
                indicesTable.addCell(aumentacion);
            }

            if (this.reportSettingsProperties.loadUseAOS()) {
                Chunk an = new Chunk("Ancho 50% OS" + System.getProperty("line.separator") + Units.miliseconds);
                an.setFont(indexFont);
                PdfPCell ancho = new PdfPCell(new Paragraph(an));
                ancho.setHorizontalAlignment(Element.ALIGN_CENTER);
                ancho.setVerticalAlignment(Element.ALIGN_MIDDLE);
                indicesTable.addCell(ancho);
            }

            if (this.reportSettingsProperties.loadUseIMC()) {
                Chunk m = new Chunk("Masa Corporal");
                m.setFont(indexFont);
                PdfPCell masa = new PdfPCell(new Paragraph(m));
                masa.setHorizontalAlignment(Element.ALIGN_CENTER);
                masa.setVerticalAlignment(Element.ALIGN_MIDDLE);
                indicesTable.addCell(masa);
            }

            if (this.reportSettingsProperties.loadUseFC()) {
                Chunk f = new Chunk("Frecuencia Card." + System.getProperty("line.separator") + "[ppm]");
                f.setFont(indexFont);
                PdfPCell freq = new PdfPCell(new Paragraph(f));
                freq.setHorizontalAlignment(Element.ALIGN_CENTER);
                freq.setVerticalAlignment(Element.ALIGN_MIDDLE);
                indicesTable.addCell(freq);
            }

            if (this.reportSettingsProperties.loadUseRS()) {
                Chunk r = new Chunk("Reflejo Sist." + System.getProperty("line.separator") + Units.miliseconds);
                r.setFont(indexFont);
                PdfPCell rs = new PdfPCell(new Paragraph(r));
                rs.setHorizontalAlignment(Element.ALIGN_CENTER);
                rs.setVerticalAlignment(Element.ALIGN_MIDDLE);
                indicesTable.addCell(rs);
            }

            if (this.reportSettingsProperties.loadUseAOD()) {
                Chunk ampCk = new Chunk(analysisResult.getAod().getValueAsString());
                ampCk.setFont(indexValueFont);
                PdfPCell ampValue = new PdfPCell(new Paragraph(ampCk));
                ampValue.setHorizontalAlignment(Element.ALIGN_CENTER);
                ampValue.setVerticalAlignment(Element.ALIGN_MIDDLE);
                indicesTable.addCell(ampValue);
            }

            if (this.reportSettingsProperties.loadUseIAR()) {
                Chunk aumCk = new Chunk(analysisResult.getIar().getValueAsString());
                aumCk.setFont(indexValueFont);
                PdfPCell aum = new PdfPCell(new Paragraph(aumCk));
                aum.setHorizontalAlignment(Element.ALIGN_CENTER);
                aum.setVerticalAlignment(Element.ALIGN_MIDDLE);
                indicesTable.addCell(aum);
            }

            if (this.reportSettingsProperties.loadUseAOS()) {
                Chunk anchCk = new Chunk(analysisResult.getAos().getValueAsString());
                anchCk.setFont(indexValueFont);
                PdfPCell anch = new PdfPCell(new Paragraph(anchCk));
                anch.setHorizontalAlignment(Element.ALIGN_CENTER);
                anch.setVerticalAlignment(Element.ALIGN_MIDDLE);
                indicesTable.addCell(anch);
            }

            if (this.reportSettingsProperties.loadUseIMC()) {
                Chunk masCk = new Chunk(analysis.getClinicalInformation().getIMCasString());
                masCk.setFont(indexValueFont);
                PdfPCell mas = new PdfPCell(new Paragraph(masCk));
                mas.setHorizontalAlignment(Element.ALIGN_CENTER);
                mas.setVerticalAlignment(Element.ALIGN_MIDDLE);
                indicesTable.addCell(mas);
            }

            if (this.reportSettingsProperties.loadUseFC()) {
                Chunk freqCk = new Chunk(analysisResult.getHeartRateAsString());
                freqCk.setFont(indexValueFont);
                PdfPCell freqC = new PdfPCell(new Paragraph(freqCk));
                freqC.setHorizontalAlignment(Element.ALIGN_CENTER);
                freqC.setVerticalAlignment(Element.ALIGN_MIDDLE);
                indicesTable.addCell(freqC);
            }

            if (this.reportSettingsProperties.loadUseRS()) {
                Chunk rs = new Chunk(analysisResult.getT().getValueAsString());
                rs.setFont(indexValueFont);
                PdfPCell rsC = new PdfPCell(new Paragraph(rs));
                rsC.setHorizontalAlignment(Element.ALIGN_CENTER);
                rsC.setVerticalAlignment(Element.ALIGN_MIDDLE);
                indicesTable.addCell(rsC);
            }

            this.document.add(indicesTable);
        }
        this.writeEmptyLine();
    }

    @Override
    protected void buildPlot(BufferedImage image) throws BadElementException, DocumentException, IOException {

        if (image != null) {
            float[] widithPlot = {0.5f, 1.5f};
            PdfPTable tablePlot = new PdfPTable(widithPlot);
            tablePlot.setWidthPercentage(70);
            tablePlot.setHorizontalAlignment(Element.ALIGN_CENTER);
            Chunk plot = new Chunk(this.reportSettingsProperties.loadPlotTitle());
            plot.setFont(new Font(fontMapper.awtToPdf(this.reportSettingsProperties.loadPlotFont())));
            PdfPCell plotTitle = new PdfPCell(new Paragraph(plot));

            plotTitle.setVerticalAlignment(Element.ALIGN_MIDDLE);
            plotTitle.setHorizontalAlignment(Element.ALIGN_CENTER);
            tablePlot.addCell(plotTitle);

            Image imagePdf = Image.getInstance(image, null);
            PdfPCell plotCell = new PdfPCell(imagePdf);
            plotCell.setFixedHeight(image.getHeight() + 20);
            plotCell.setHorizontalAlignment(Element.ALIGN_CENTER);
            plotCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
            tablePlot.addCell(plotCell);

            this.document.add(tablePlot);
            this.writeEmptyLine();
        }
        this.writeEmptyLine();
    }

    @Override
    protected void buildConclusions(Analysis analysis, Report report) throws DocumentException {
        Font titleFont = new Font(fontMapper.awtToPdf(this.reportSettingsProperties.loadBodyTextTitleFont()));
        Font textFont = new Font(fontMapper.awtToPdf(this.reportSettingsProperties.loadBodyTextFont()));

        if ((report.getComments() != null) && (!report.getComments().isEmpty())) {
            Chunk coment = new Chunk(EntityDescriptions.COMMENTS + ":" + System.getProperty("line.separator"));
            coment.setFont(titleFont);
            this.document.add(coment);
            Chunk coments = new Chunk(report.getComments());
            coments.setFont(textFont);
            this.document.add(coments);
            this.writeEmptyLine();
        }

        boolean iarEmpty = ((report.getCommentIAR() == null) || (report.getCommentIAR().isEmpty()));
        boolean aosEmpty = (report.getCommentAOS() == null) || (report.getCommentAOS().isEmpty());
        boolean aodEmpty = ((report.getCommentAOD() == null) || (report.getCommentAOD().isEmpty()));

        if ((!iarEmpty) || (!aodEmpty) || (!aosEmpty)) {

            Chunk indice = new Chunk(EntityDescriptions.INDEXS + ":" + System.getProperty("line.separator"));
            indice.setFont(titleFont);
            this.document.add(indice);
            this.document.add(new Paragraph());

            int samples = 0;
            try {
                AverageByDecade averageByDecade = FacadeDB.getInstance().getAveragesBroker().getAverageByPatient(analysis.getPatient());
                if (averageByDecade != null) {
                    samples = averageByDecade.getSamples();
                }
            } catch (ExceptionDAO aO) {
                //
            }

            Chunk detail = new Chunk(ReportTexts.ideal_characteristics + System.getProperty("line.separator")
                    + ReportTexts.values_to + analysis.getPatient().getDecade() + ReportTexts.decade_and_averages + String.valueOf(samples) + System.getProperty("line.separator"));
            Font detailFont = new Font(fontMapper.awtToPdf(this.reportSettingsProperties.loadBodyTextFont().deriveFont(Font.ITALIC, textFont.getSize() - 2)));
            detail.setFont(detailFont);

            this.document.add(detail);

            if (!iarEmpty) {
                Chunk indiceIAR = new Chunk(report.getCommentIAR() + System.getProperty("line.separator"));
                indiceIAR.setFont(textFont);
                this.document.add(indiceIAR);
            }

            if (!aosEmpty) {
                Chunk indiceAOS = new Chunk(report.getCommentAOS() + System.getProperty("line.separator"));
                indiceAOS.setFont(textFont);
                this.document.add(indiceAOS);
            }

            if (!aodEmpty) {
                Chunk indiceAOD = new Chunk(report.getCommentAOD() + System.getProperty("line.separator"));
                indiceAOD.setFont(textFont);
                this.document.add(indiceAOD);
            }
            this.writeEmptyLine();
        }

        if ((report.getAllBackground() != null) && (!report.getAllBackground().isEmpty())) {

            Chunk antedecente = new Chunk(EntityDescriptions.BACKGROUNDS + ":" + System.getProperty("line.separator"));
            antedecente.setFont(titleFont);
            this.document.add(antedecente);

            Chunk antecedentes = new Chunk(report.getAllBackground());
            antecedentes.setFont(textFont);
            this.document.add(antecedentes);

            this.writeEmptyLine();
        }

        if ((report.getConclusion() != null) && (!report.getConclusion().isEmpty())) {
            Chunk concluson = new Chunk(EntityDescriptions.CONCLUSION + ":" + System.getProperty("line.separator"));
            concluson.setFont(titleFont);
            this.document.add(concluson);
            Chunk conclusiones = new Chunk(report.getConclusion());
            conclusiones.setFont(textFont);
            this.document.add(conclusiones);
        }

    }

    @Override
    public void build(Analysis analysis, Report report,
            AnalysisResult analysisResult, File file) {
        try {
            this.file = file;
            this.createDocument();
            this.buildHeader();
            this.buildPatientInfo(analysis);
            this.buildParamsInfo(analysis, report, analysisResult);
            this.buildPlot(report.getGraphic());
            this.buildConclusions(analysis, report);
            this.closeDocument();
        } catch (DocumentException ex) {
            ex.printStackTrace();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    @Override
    protected void createDocument() throws DocumentException,
            FileNotFoundException,
            IOException {
        this.document = new Document(PageSize.LEGAL);
        PdfWriter.getInstance(this.document,
                new FileOutputStream(this.file.getAbsoluteFile()));
        this.document.open();
        this.document.addTitle("SERVICIO UNIVERSITARIO DE SALUD");
        this.document.addSubject("Documento generado por Systole para el Servicio Universitario de Salud");
        this.document.addCreator("Systole");
        this.document.addAuthor("Laboratorio de Bioingenieria de la UNMDP");
    }

    @Override
    protected void closeDocument() {
        this.document.close();
    }
}
